<template>
  <m-window-frame
    title="选择框架视图"
    :ok-loading="okLoading"
    class="v-model-create-project-by-template"
    @ok="handleOk"
    @cancel="handleCancel"
  >
    <attr-tips type="checkbox"></attr-tips>
    <select-tree
      class="select-template"
      :tree-data="treeData"
      :load-nodes="loadNodes"
      checkable
      show-node-label
      lazy
      @handle-node-click="node => handleNodeClick(node, !node.checked)"
      @handle-node-check="node => handleNodeClick(node, !node.checked)"
    ></select-tree>
  </m-window-frame>
</template>

<script lang="ts" setup>
import MWindowFrame from "@/common/ipcWindow/WindowFrame.vue";
import AttrTips from "@/common/attrTip/AttrTip.vue";
import SelectTree from "@/modules/model/modals/modelTreeSelect/components/SelectTree.vue";
import { onBeforeMount, reactive, ref } from "vue";
import { MTreeNode } from "@/common/Tree/MTreeNode";
import { Project } from "@/mdesign-lib/mdesign-app.umd.js";
import { modelService, projectService } from "@/mdesign-lib/mdesign-app.umd.js";
import { ProjectConfig } from "@/modules/model/project/ProjectConfig";
import { NodeData } from "@/modules/model/project/IGraphNode";
import { ipcWindowUtil } from "@/mdesign-lib/mdesign-app.umd.js";
import { treeForEach } from "@/util/common";
import { ModelFrom } from "@/mdesign-lib/mdesign-app.umd.js";
/**
 * - 组件说明
 *   - 隐藏根模型且显示根模型下一层模型
 *   - 暂时不支持关系组的选择（可根据用户反馈再作添加）
 */
type TreeNodeType = MTreeNode<NodeData>;
const projectId = app.$route.query.projectId as string;
const project = ref<typeof app.activeProject>();
const projectConfig = ref<ProjectConfig | undefined>();
const treeData = ref<Array<TreeNodeType>>([]);
const treeNodeMap = new Map<NodeData["id"], TreeNodeType>();
const okLoading = ref(false);
const cancelDisabled = ref(true);
const confirmDisabled = ref(true);
const windowName = "CreateProjectByTemplateWindow";

onBeforeMount(async () => {
  projectConfig.value = await projectService.getProjectInfo(projectId);
  project.value = new Project(projectConfig.value);
  const treeNodes = (await modelService.getChildNodeDatas(projectId, projectConfig.value.rootId))
    .map(nodeData => createTreeNode(nodeData, true, undefined))
    .filter(child => child.visible && child.data.from == ModelFrom.USER_CREATE);
  treeData.value.push(...treeNodes);
  cancelDisabled.value = false;
  confirmDisabled.value = false;
});

async function loadNodes(node: TreeNodeType) {
  if (!node.loaded) {
    node.loaded = true;
    node.loading = true;
    const childNodes = (await modelService.getChildNodeDatas(projectId, node.data.id))
      .map(nodeData => createTreeNode(nodeData, node.checked, node))
      .filter(child => child.visible && child.data.from == ModelFrom.USER_CREATE);
    node.children.push(...childNodes);
  }

  // 暂未考虑关系组
  return node.children;
}
/**
 * 节点选择交互场景示例
 *  1. 选中子节点时，应该选中父节点
 *  2. 选中节点时，选中所有子节点
 *  3. 取消勾选节点时，不勾选所有子节点
 */
function handleNodeClick(node: TreeNodeType, checked: TreeNodeType["checked"]) {
  node.checked = checked;
  // 如果选中当前节点，需要向上选中父节点
  if (node.checked) {
    let parentId = node.parentId;
    while (parentId) {
      const parent = treeNodeMap.get(parentId as NodeData["id"]);
      if (parent) {
        parent.checked = checked;
        parentId = parent.parentId;
      } else break;
    }
  }
  node.children.forEach(child => handleNodeClick(child, checked));
}

function createTreeNode(nodeData: NodeData, checked: TreeNodeType["checked"], parent: TreeNodeType | undefined) {
  const treeNode = reactive(new MTreeNode<NodeData>(nodeData));
  treeNodeMap.set(nodeData.id, treeNode);
  treeNode.checked = checked;
  treeNode.icon = nodeData.icon;
  treeNode.visible = nodeData.visible;
  treeNode.disabled = false;
  treeNode.isLeaf = !nodeData.hasChild;
  treeNode.parent = parent;
  treeNode.parentId = parent?.data.id;
  return treeNode;
}

function handleOk() {
  const selected = new Set<NodeData["id"]>();
  const unSelected = new Set<NodeData["id"]>();
  treeForEach(treeData.value, node => {
    if (node.checked == false) {
      unSelected.add(node.data.id);
      selected.delete(node.data.id);
    } else {
      selected.add(node.data.id);
      unSelected.delete(node.data.id);
    }
  });
  ipcWindowUtil.closeWindow({ windowName, success: true, data: { selected, unSelected } });
}

function handleCancel() {
  ipcWindowUtil.closeWindow({ windowName, success: false });
}
</script>

<style scoped lang="scss">
.select-template {
  padding-left: 20px;
  padding-top: 10px;
}
</style>
